﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using GalaSoft.MvvmLight.Threading;
using pluginService;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Threading;
using wpf.Model;

namespace wpf.Utils
{

    public enum LPluginState
    {
        无状态 = 0,
        加载插件 = 1
    }


    /// <summary>
    /// 单例插件帮助类
    /// </summary>
    public partial class LPlugin : ObservableObject
    {

        private LPluginState lPluginState;


        [ObservableProperty]
        private string pluginText = string.Empty;
        private IPluginManage pluginManage;


        public record class LPluginDLL(string Name, string assemblyPath);

        public event Action<List<PluginViewModel>> FlashPulginView;
        public event Action<string> FlashTextView;


        public LPlugin()
        {
            DispatcherHelper.Initialize();
            pluginManage = new IPluginManage();
            LoadPlugin = new RelayCommand(LoadPluginAsync, CanExcute);
            LoadClass = new RelayCommand<string>(i => LoadClassAsync(i));
            SendMessage = new RelayCommand<string>(msg => SendMessageAsync(msg));
        }

        private bool CanExcute()
        {
            return lPluginState == LPluginState.无状态;
        }

        public IRelayCommand LoadPlugin { get; }

        public IRelayCommand<string> LoadClass { get; }

        public IRelayCommand<string> SendMessage { get; }

        /// <summary>
        /// 查找当前程序集Plugin文件夹下dll
        /// </summary>
        public void LoadPluginAsync()
        {
            PluginText += ".";
            //子线程运行保证不影响主线程
            _ = Task.Run(() =>
            {
                try
                {
                    //MessageBox.Show("加载插件中");
                    lPluginState = LPluginState.加载插件;

                    var basePath = AppDomain.CurrentDomain.BaseDirectory;
                    var pluginPath = Path.Combine(basePath, "LPlugins");
                    var dires = Directory.GetFiles(pluginPath);

                    for (int i = 0; i < dires.Length; i++)
                    {
                        var curAss = Assembly.LoadFrom(dires[i]);

                        //添加程序集中插件

                        var types = curAss.GetTypes();
                        foreach (var ty in types)
                        {
                            if (!ty.IsClass || ty.IsNotPublic) continue;
                            if(ty.IsSubclassOf(typeof(PluginBaseHandle)))
                            {
                                var insertPlugin = Activator.CreateInstance(ty) as PluginBaseHandle;
                                if (insertPlugin is not null)
                                {
                                    pluginManage.Add(insertPlugin);
                                }
                            }
                        }

                    }



                    FlashPulginView.Invoke(pluginManage.PluginNamesDic.Select(d => new PluginViewModel() { Name = d.Key, Open = d.Value ? "已启用" : "已禁用" }).ToList());

                    //MessageBox.Show("加载插件成功");
                }
                catch (Exception)
                {
                    //MessageBox.Show("加载插件异常");

                }
                finally
                {
                    lPluginState = LPluginState.无状态;
                }
            });

        }

        public void LoadClassAsync(string pluginName) 
        {
            if (string.IsNullOrEmpty(pluginName))
                return;

            pluginManage.Open(pluginName);

            FlashPulginView.Invoke(pluginManage.PluginNamesDic.Select(d => new PluginViewModel() { Name = d.Key, Open = d.Value ? "已启用" : "已禁用" }).ToList());
        }

        public void SendMessageAsync(string message)
        {
            var res = pluginManage.PluginHandle.OnRecvice(new PluginData() { Message = message });
            FlashTextView.Invoke(res);
        }


    }
}
